#include <string>

//Lexical Rules
#define DIGIT			"[0-9]"
#define LETTER			"[a-zA-Z]"
#define INTEGER			DIGIT + std::string("+")
#define IDENT			LETTER + std::string("[a-zA-Z0-9#]*")

//Auxiliary Grammar Rules
#define synonym			IDENT
#define stmtRef			synonym + std::string("|_|") + INTEGER
#define entRef			synonym + std::string("|_|") + "[\"]" + IDENT + "[\"]"
#define design_entity	"(stmt|assign|while|variable|constant|prog_line)"

//Relationship Grammar Rules
#define Reg_ModifiesS		std::string("(Modifies)[\\s]*[(][\\s]*(") + stmtRef + ")[\\s]*,[\\s]*(" + entRef + ")[\\s]*[)]"
#define Reg_UsesS			std::string("(Uses)[\\s]*[(][\\s]*(") + stmtRef + ")[\\s]*,[\\s]*(" + entRef + ")[\\s]*[)]"
#define Reg_Parent			std::string("(Parent)[\\s]*[(][\\s]*(") + stmtRef + ")[\\s]*,[\\s]*(" + stmtRef + ")[\\s]*[)]"
#define Reg_ParentT			std::string("(Parent[*])[\\s]*[(][\\s]*(") + stmtRef + ")[\\s]*,[\\s]*(" + stmtRef + ")[\\s]*[)]"
#define Reg_Follows			std::string("(Follows)[\\s]*[(][\\s]*(") + stmtRef + ")[\\s]*,[\\s]*(" + stmtRef + ")[\\s]*[)]"
#define Reg_FollowsT		std::string("(Follows[*])[\\s]*[(][\\s]*(") + stmtRef + ")[\\s]*,[\\s]*(" + stmtRef + ")[\\s]*[)]"
#define relRef			std::string("(") + Reg_ModifiesS + "|" + Reg_UsesS + "|" + Reg_Parent + "|" + Reg_ParentT + "|" + Reg_Follows + "|" + Reg_FollowsT +")"

//Grammar Rules for Select Clause
#define declaration		design_entity + std::string("[\\s]*(") + synonym + ")([\\s]*,[\\s]*" + synonym + ")*" + "[\\s]*;[\\s]*"
#define select_cl		std::string("(") + declaration + ")*[\\s]*(Select)[\\s]*(" + synonym + ")[\\s]*(" + suchthat_cl "[\\s]*|" + pattern_cl "[\\s]*)*"
#define suchthat_cl		std::string("(such[\\s]*that)[\\s]*") + relRef
#define pattern_cl		std::string("(pattern)[\\s]*(") + synonym + ")[\\s]*[(][\\s]*(" + entRef + ")[\\s]*,[\\s]*(_[\"]"+synonym+"[\"]_|_)[\\s]*[)]"

//Self defined clauses for extracting purposes
#define result_cl		std::string("(Select)[\\s]*(") + synonym + ")"
#define var_literal		std::string("[\"]") + IDENT + "[\"]|[_]" //var_literal is defined as either "x" or _
#define any_value		std::string("[_]")
#define stmt_literal	INTEGER